/******************************************************************************
 * This file is part of libemb.
 *
 * libemb is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * libemb is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with libemb.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Project: Embedme
 * Author : FergusZeng
 * Email  : cblock@126.com
 * git	  : https://gitee.com/newgolo/embedme.git
 * Copyright 2014~2020 @ ShenZhen ,China
*******************************************************************************/
#include "libemb/Tracer.h"
#include "libembx/EVIO.h"

namespace libembx{
using namespace libemb;

EVWatcher::EVWatcher()
{
}

EVWatcher::~EVWatcher()
{
}

int EVWatcher::type()
{
	return m_type;
}


EVIO::EVIO()
{
	m_type = EVIO_TYPE_IO;
}

EVIO::~EVIO()
{
	if (m_fd>0)
	{
		::close(m_fd);
	}
}

bool EVIO::setEvent(int fd, int evioEvt)
{
	if (fd<0)
	{
		return false;
	}
	m_fd = fd;
	m_evio.set(m_fd,evioEvt);
    m_evio.set<EVIO,&EVIO::evCallBack>(this);		
	return true;
}

void EVIO::evCallBack(    ev::io& evio, int revents)
{
	if (revents & ev::READ)
	{
		onEvent(EVIO_EVT_READ);
	}
	else if (revents & ev::WRITE)
	{
		onEvent(EVIO_EVT_WRITE);
	}
}


EVTimer::EVTimer()
{
	m_type = EVIO_TYPE_TIMER;
}
EVTimer::~EVTimer()
{

}

bool EVTimer::setTimer(int msTimeout, bool repeat)
{
	if (msTimeout<0)
	{
		return false;
	}
	ev_tstamp timeout = (ev_tstamp)msTimeout;
	timeout = timeout/1000;
	m_evtimer.set(timeout,repeat?1.0:0.0);
	m_evtimer.set<EVTimer,&EVTimer::evCallBack>(this);	
	return true;
}

void EVTimer::evCallBack(ev::timer& evtimer, int revents)
{
	if (revents & ev::TIMER)
	{
		onTimeout();
	}
}


EVSignal::EVSignal()
{

}

EVSignal::~EVSignal()
{
	m_type = EVIO_TYPE_SIGNAL;
}

bool EVSignal::setSignal(int signum)
{
	m_evsig.set(signum);
	m_evsig.set<EVSignal,&EVSignal::evCallBack>(this);	
	return true;
}

void EVSignal::evCallBack(ev::sig& evsignal, int revents)
{
	if (revents & ev::SIGNAL)
	{
		onSignal();
	}
}

EVLoop::EVLoop()
{
}

EVLoop::~EVLoop()
{
}

bool EVLoop::initialize()
{
	/* 必须使用动态loop,default_loop是单例,无法满足多线程需求 */
	m_dynLoop = std::make_unique<ev::dynamic_loop>(EVFLAG_AUTO|EVBACKEND_EPOLL);
	if (!m_dynLoop)
	{
		return false;
	}
	return true;
}

bool EVLoop::addWatcher(EVWatcher* watcher)
{
	if (!m_dynLoop)
	{
		return false;
	}
	switch(watcher->type()){
	case EVIO_TYPE_IO:
		((EVIO*)watcher)->m_evio.set((struct ev_loop*)(*m_dynLoop));
		((EVIO*)watcher)->m_evio.start();
		break;
	case EVIO_TYPE_TIMER:
		((EVTimer*)watcher)->m_evtimer.set((struct ev_loop*)(*m_dynLoop));
		((EVTimer*)watcher)->m_evtimer.start();
		break;
	case EVIO_TYPE_SIGNAL:
		((EVSignal*)watcher)->m_evsig.set((struct ev_loop*)(*m_dynLoop));
		((EVSignal*)watcher)->m_evsig.start();
		break;
	default:
		return false;
	}
	return true;
}

bool EVLoop::removeWatcher(EVWatcher* watcher)
{
	if (!m_dynLoop)
	{
		return false;
	}
	switch(watcher->type()){
	case EVIO_TYPE_IO:
		((EVIO*)watcher)->m_evio.stop();
		break;
	case EVIO_TYPE_TIMER:
		((EVTimer*)watcher)->m_evtimer.stop();
		break;
	case EVIO_TYPE_SIGNAL:
		((EVSignal*)watcher)->m_evsig.stop();
		break;
	default:
		return false;
	}
	return true;
}

void EVLoop::run(Thread& thread)
{
	while(!m_dynLoop)
	{
		Thread::msleep(10);
	}
	while(1)
	{
		 m_dynLoop->run();
		 break;
	}
}



}

